package cn.tannn.tcache.server;


import cn.tannn.tcache.core.Command;
import cn.tannn.tcache.core.Commands;
import cn.tannn.tcache.core.Reply;
import cn.tannn.tcache.core.Tcache;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import lombok.extern.slf4j.Slf4j;

import static cn.tannn.tcache.core.Command.CRLF;
import static cn.tannn.tcache.resp.ArrayProtocol.array;
import static cn.tannn.tcache.resp.ErrorProtocol.error;
import static cn.tannn.tcache.resp.IntegerProtocol.integer;
import static cn.tannn.tcache.resp.StringProtocol.bulkString;
import static cn.tannn.tcache.resp.StringProtocol.simpleString;

/**
 * 消息处理器
 * arg 取值格式 参考 readme 中的数据
 *
 * @author <a href="https://t.tannn.cn/">tnnn</a>
 * @version V1.0
 * @date 2024/6/12 下午9:54
 */
@Slf4j
public class TcacheHandler extends SimpleChannelInboundHandler<String> {

    /**
     * 数据容器
     */
    public static final Tcache cache = new Tcache();

    @Override
    protected void channelRead0(ChannelHandlerContext ctx
            , String message) throws Exception {

        // 根据换行截取
        String[] args = message.split(CRLF);
        log.debug("tcacheHandler message: {}", String.join(",", args));

        // 第二个位置等于 redis输入的命令
        String cmd = args[2].toUpperCase();

        Command command = Commands.get(cmd);
        if (command != null) {
            try {
                Reply<?> reply = command.exec(cache, args);
                log.debug("CMD[{}] => {} => {}", cmd, reply.getType(), reply.getValue());
                replyContext(ctx, reply);
            } catch (Exception exception) {
                Reply<?> reply = Reply.error("EXP exception with msg: '" + exception.getMessage() + "'");
                replyContext(ctx, reply);
            }
        } else {
            Reply<?> unsupported = Reply.error("ERR unsupported command '" + cmd + "'");
            replyContext(ctx, unsupported);
        }
    }


    /**
     * 处理命令
     *
     * @param ctx   ChannelHandlerContext
     * @param reply 命令详情
     */
    private void replyContext(ChannelHandlerContext ctx, Reply<?> reply) {
        switch (reply.getType()) {
            case SIMPLE_STRING:
                simpleString(ctx, (String) reply.getValue());
                break;
            case BULK_STRING:
                bulkString(ctx, (String) reply.getValue());
                break;
            case INT:
                integer(ctx, (int) reply.getValue());
                break;
            case ARRAY:
                array(ctx, (String[]) reply.getValue());
                break;
            case ERROR:
                error(ctx, reply.getValue().toString());
                break;
            default:
                simpleString(ctx, reply.getValue().toString());
        }
    }


}
